#include "touch.h"
static const char *TAG = "i2c-simple-example";

static QueueHandle_t gpio_evt_queue = NULL;
static void gpio_task_example(void* arg);
static void  gpio_isr_handler(void* arg);
static void Cst816ReadPosition(void);
static struct indev_t cst816_touch_sta;

static void  gpio_isr_handler(void* arg)
{
    uint32_t gpio_num = (uint32_t) arg;
    xQueueSendFromISR(gpio_evt_queue, &gpio_num, NULL);
    //printf("hello\n");
}

void cts816tInit(void)
{
    gpio_reset_pin(TP_RST);
    /* Set the GPIO as a push/pull output */
    gpio_set_direction(TP_RST, GPIO_MODE_OUTPUT);
    gpio_set_level(TP_RST,0);
    vTaskDelay(10 / portTICK_PERIOD_MS);
    gpio_set_level(TP_RST,1);
    vTaskDelay(10 / portTICK_PERIOD_MS);

    gpio_config_t io_conf = {};
    io_conf.intr_type = GPIO_INTR_POSEDGE;
    io_conf.pin_bit_mask = GPIO_INPUT_PIN_SEL;
    io_conf.mode = GPIO_MODE_INPUT;
    io_conf.pull_up_en = 0;
    gpio_config(&io_conf);
    gpio_set_intr_type(GPIO_INPUT_IO_0, GPIO_INTR_POSEDGE);

    gpio_evt_queue = xQueueCreate(10, sizeof(uint32_t));
    xTaskCreate(gpio_task_example, "gpio_task_example", 2560, NULL, 10, NULL);
    gpio_install_isr_service(ESP_INTR_FLAG_DEFAULT);

    gpio_isr_handler_add(GPIO_INPUT_IO_0, gpio_isr_handler, (void*) GPIO_INPUT_IO_0);
}





static void gpio_task_example(void* arg)
{
    uint32_t io_num;
    for(;;) {
        if(xQueueReceive(gpio_evt_queue, &io_num, portMAX_DELAY)) {
            Cst816ReadPosition();
        }
    }
}

/**
 * @brief Read a sequence of bytes from a MPU9250 sensor registers
 */
static esp_err_t cts816tRegisterRead(uint16_t reg_addr, uint8_t *data, size_t write_data_len,size_t len)
{
    uint8_t write_buf[2]; 
    if(write_data_len == 2)
    {
        write_buf[0] = (reg_addr >> 8) &0xff, 
        write_buf[1] = (reg_addr) &0xff;
    }else if(write_data_len == 1)
    {
         write_buf[0] = (reg_addr) &0xff;
    }else{
        return ESP_FAIL;
    }
    return i2c_master_write_read_device(I2C_MASTER_NUM, MPU9250_SENSOR_ADDR, write_buf, write_data_len, data, len, I2C_MASTER_TIMEOUT_MS / portTICK_PERIOD_MS);
}

static esp_err_t cts816tReadBytes(uint16_t reg_addr, uint8_t *data, size_t write_data_len,size_t len)
{
    uint8_t write_buf[2]; 
    if(write_data_len == 2)
    {
        write_buf[0] = (reg_addr >> 8) &0xff, 
        write_buf[1] = (reg_addr) &0xff;
    }else if(write_data_len == 1)
    {
         write_buf[0] = (reg_addr) &0xff;
    }else{
        return ESP_FAIL;
    }
    return i2c_master_write_read_device(I2C_MASTER_NUM, TP_ADDR, write_buf, write_data_len, data, len, I2C_MASTER_TIMEOUT_MS / portTICK_PERIOD_MS);
}

/**
 * @brief Write a byte to a MPU9250 sensor register
 */
static esp_err_t cts816tWriteByte(uint16_t reg_addr, uint8_t data)
{
    int ret;
    uint8_t write_buf[3] = {(reg_addr >> 8) &0xff, (reg_addr) &0xff,data};

    ret = i2c_master_write_to_device(I2C_MASTER_NUM, MPU9250_SENSOR_ADDR, write_buf, sizeof(write_buf), I2C_MASTER_TIMEOUT_MS*3 / portTICK_PERIOD_MS);

    return ret;
}


void test_read_addr()
{
    uint8_t data = 0;
    uint8_t reg_addr = 0xa7;
    esp_err_t ret = 0;
    for(int i = 0; i <=127; i++)
    {
        ret = i2c_master_write_read_device(I2C_MASTER_NUM,i,&reg_addr,1,&data,1, I2C_MASTER_TIMEOUT_MS / portTICK_PERIOD_MS);
        if(ret == ESP_OK )
        {
                ESP_LOGI(TAG, "sendor_id  %x",i);
              vTaskDelay(1 / portTICK_PERIOD_MS);
        }
    }
}


int cts816EnterBootMode(void)
{
    esp_err_t ret = 0;
    uint8_t sendor_id = 0;

    ret = cts816tWriteByte(0xA001,0xab);
    ESP_LOGI(TAG,"tp write ret  %d",ret);
    cts816tRegisterRead(0xA003,&sendor_id,2,1);
    //ESP_LOGI(TAG,"sendor_id %x",sendor_id);
    if(sendor_id == 0xc1)
    {
        ESP_LOGI(TAG,"sendor id match success\n");
        return 0;
    }
    
    return  -1;
}

uint16_t cst816_read_checksum()
{
    union{
        uint32_t sum;
        uint8_t buf[4];
    }checksum;
    uint8_t cmd[3];

    cmd[0] = 0;
    cts816tWriteByte(0xa003,cmd[0]);
    vTaskDelay(500 / portTICK_PERIOD_MS);
    checksum.sum = 0;

    cts816tRegisterRead(0xa008,checksum.buf,2,2);
                ESP_LOGI(TAG, "checksum  %ld",checksum.sum);
    return checksum.sum;
}

void ctp_hynitron_update(void)
{
    if(cts816EnterBootMode() == 0)
    {
        if(sizeof(app_bin) > 10)
        {
            uint16_t start_addr = app_bin[1];
            uint16_t length = app_bin[3];
            uint16_t checksum = app_bin[5];
            start_addr <<= 8;
            start_addr |= app_bin[0];
            length <<= 8;
            length |= app_bin[2];
            checksum <<= 8;
            checksum |= app_bin[4];
            ESP_LOGI(TAG,"checksum  %d",checksum);
            if(cst816_read_checksum() != checksum)
            {
                ESP_LOGI(TAG, "cst816 check sum failed\n"); 
            }else{

            }
        }
    }
}

void CaptureDaaHandle(uint8_t *tp_temp)
{
    int16_t pdwSampleX,pdwSampleY; 
    //int16_t finger_num = tp_temp[2];  //手指个数
    pdwSampleX = (int16_t)((tp_temp[3] & 0x0F)<<8)+   (uint16_t)tp_temp[4];
    pdwSampleY = (int16_t)((tp_temp[5] & 0x0F)<<8) +  (uint16_t)tp_temp[6];
  //  ESP_LOGI(TAG, "x = %d, y  %d,mode = %d,finger_num = %d\n",pdwSampleX,pdwSampleY,tp_temp[1],finger_num); 
    
    cst816_touch_sta.touch_status = 1;
    cst816_touch_sta.x_coordinate = pdwSampleX;
    cst816_touch_sta.y_coordinate = pdwSampleY;
    // if(tp_temp[1] == 0x00)      //报点模式
    // {
    //     ESP_LOGI(TAG, "tp_temp = 0\n"); 
    // }else if(tp_temp[1] == 0x05)
    // {
    //      ESP_LOGI(TAG, "tp_temp = 5\n"); 
    // }else if(tp_temp[1] == 0x0c)
    // {
    //      ESP_LOGI(TAG, "tp_temp = c\n"); 
    // }
}


int GetTpIsTouch(void)
{
    if(cst816_touch_sta.touch_status == 1)
    {
        cst816_touch_sta.touch_status = 0;
        return 1;
    }
    return 0;
}

void  GetTpPositon(int16_t *x,int16_t *y)
{
    (*x) = cst816_touch_sta.x_coordinate;
    (*y) = cst816_touch_sta.y_coordinate;
}

static void Cst816ReadPosition(void)
{
    uint8_t data[10];
    cts816tReadBytes(0x00,data,1,7);
    CaptureDaaHandle(&data[0]);
}


